<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es5 创建原型对象的方法</title>
  <!-- 
  在 JavaScript ES5 中，创建原型对象的方法有几种常见的方式。原型对象用于定义构造函数创建的实例共享的属性和方法。
  1. 使用构造函数创建原型对象
  构造函数是创建对象的主要方式。在构造函数中，可以通过  `prototype`  属性定义原型对象。
  function Person(name) {
      this.name = name; // 实例属性
  }

  // 定义原型方法
  Person.prototype.sayHello = function() {
      console.log("Hello, " + this.name);
  };

  var alice = new Person("Alice");
  alice.sayHello(); // 输出: Hello, Alice
  在这个例子中， `Person.prototype`  定义了一个方法  `sayHello` ，所有通过  `Person`  构造函数创建的实例都可以共享这个方法。

  2. 使用 Object.create() 创建原型对象
  `Object.create()`  方法可以创建一个新对象，并将其原型设置为指定的对象。这是一种更灵活的方式，可以用于创建具有特定原型的新对象。
  var personPrototype = {
      sayHello: function() {
          console.log("Hello, " + this.name);
      }
  };

  // 创建新对象，并设置原型
  var alice = Object.create(personPrototype);
  alice.name = "Alice";
  alice.sayHello(); // 输出: Hello, Alice
  在这个例子中， `alice`  对象通过  `Object.create(personPrototype)`  创建，并继承了  `personPrototype`  中的方法。

  3. 直接修改原型对象
  可以直接修改构造函数的原型对象，以添加新的属性和方法。这种方式可以在构造函数定义之后进行扩展。
  function Person(name) {
      this.name = name;
  }

  // 初始定义
  Person.prototype.sayHello = function() {
      console.log("Hello, " + this.name);
  };

  // 之后再添加方法
  Person.prototype.sayGoodbye = function() {
      console.log("Goodbye, " + this.name);
  };

  var bob = new Person("Bob");
  bob.sayHello();    // 输出: Hello, Bob
  bob.sayGoodbye();  // 输出: Goodbye, Bob
  4. 总结
  在 ES5 中，创建原型对象的方法主要包括使用构造函数定义原型、使用  `Object.create()`  方法创建原型对象，以及直接修改原型对象。通过原型对象定义的方法可以实现代码的重用和共享，减少内存占用。理解这些方法对于有效地使用 JavaScript 的面向对象编程非常重要。
   -->
</head>
<body>

  <script>
    // 工具函数
    // 创建对象的过程
    function createObject(proto) {
      function F() {}
      F.prototype = proto;
      return new F();
    }

    // 将Subtype和Supertype关联起来
    // 寄生式函数
    function inherit(Subtype, Supertype) {
      Subtype.prototype = createObject(Supertype.prototype);
      Object.defineProperty(Subtype.prototype, 'constructor', {
        enumerable: false,
        configurable: true,
        writable: true,
        value: Subtype
      })
    }

    /*
    满足什么条件:
      1.必须创建出来一个对象
      2.这个对象的隐式原型必须指向父类的显式原型
      3.将这个对象赋值给子类的显式原型
    */
    function Person(name, age, height) {}
    function Student() {}

    inherit(Student, Person);

    // 1.之前的做法: 但是不想要这种做法
    // var p = new Person()
    // Student.prototype = p

    // 2. 寄生式函数
    // 2.1 方案一:
    const obj = {}
    // obj.__proto__ = Person.prototype
    Object.setPrototypeOf(obj, Person.prototype)
    Student.prototype = Person.prototype

    // 2.2 方案二:
    function F() {}
    F.prototype = Person.prototype
    Student.prototype = new F()

    // 2.3 方案三:
    const obj2 = Object.create(Person.prototype)
    console.log(obj2.__proto__ === Person.prototype) // true
    Student.prototype = obj2;
    


  </script>
  
</body>
</html>